<template>
  <div class="table-box">
    <el-affix :offset="0" :style="affixStyle" v-if="affixRoute">
      <el-tag v-if="hideTableSelect && tableInfo.tableInfoId" @mouseenter="hideTableSelect = false" round>
        {{ tableInfo.tableInfos.find((info: API.TableInfoVo) => info.id == tableInfo.tableInfoId)?.name ?? "" }}
      </el-tag>
      <el-select
        v-else
        v-model="tableInfo.tableInfoId"
        filterable
        placeholder="表名"
        popper-class="tableInfoOptions"
        @mouseleave="mouseleave"
      >
        <el-option
          v-for="item in tableInfo.tableInfos"
          :key="item.id"
          :label="item.name"
          :value="item.id"
          @click="hideTableSelect = true"
        >
          <span>{{ item.name }}</span>
          <span style="margin-left: 22px; font-size: 13px; color: var(--el-text-color-secondary)">{{ item.tableName }}</span>
        </el-option>
      </el-select>
    </el-affix>

    <ProTable
      ref="proTable"
      :columns="columnList"
      :request-api="getTableList"
      :init-param="initParam"
      :data-callback="dataCallback"
      @reset="resetSearchParam"
    >
      <!-- 表格 header 按钮 -->
      <template #tableHeader>
        <el-space :size="4" spacer=" ">
          <el-button type="primary" :icon="CirclePlus" @click="handlerTable(DialogType.add)">新增</el-button>
          <el-button :icon="Top" @click="toMenu" v-if="affixRoute">升级为左侧菜单</el-button>
          <template v-if="aggColumn.length > 0">
            <el-space :size="4" spacer=":" v-for="item in aggColumn" :key="item.id">
              <el-text class="mx-1" size="default">{{ item.columnName }}</el-text>
              <el-text class="mx-1" size="default">{{ aggResult[item.columnCode] || 0 }}</el-text>
            </el-space>
          </template>
        </el-space>
      </template>

      <template #[`${primaryKeyCode}Header`]="scope">
        <el-space direction="vertical">
          <el-text class="mx-1" type="primary">主键-{{ scope.column.label }}</el-text>
        </el-space>
      </template>
      <template v-for="(v, k) in formatTableColumn" #[k]="scope" :key="k">
        {{ v[scope.row[k]] }}
      </template>
      <!-- Expand -->
      <!-- 表格操作 -->
      <template #operation="scope">
        <el-button type="primary" :disabled="!primaryKeyCode" link :icon="View" @click="handlerTable(DialogType.show, scope.row)">
          查看
        </el-button>
        <el-button
          type="primary"
          :disabled="!primaryKeyCode"
          link
          :icon="EditPen"
          @click="handlerTable(DialogType.edit, scope.row)"
          >编辑
        </el-button>
        <el-button
          type="danger"
          :disabled="!primaryKeyCode"
          link
          :icon="Delete"
          @click="handlerTable(DialogType.delete, scope.row)"
          >删除
        </el-button>
      </template>
    </ProTable>

    <AddDataDialog
      :columns="columns"
      ref="addDataDialogRef"
      title="添加"
      :primary-key="primaryKeyCode"
      :table-info-id="tableInfo.tableInfoId"
      @submit-callback="reloadData"
    ></AddDataDialog>
  </div>
</template>

<script setup lang="tsx" name="tableData">
import { computed, onMounted, provide, reactive, ref, watch } from "vue";
import { pageConverter } from "@/utils/pageUtils";
import { useRoute, useRouter } from "vue-router";
import ProTable from "@/components/ProTable/index.vue";
import { ProTableInstance } from "@/components/ProTable/interface";
import { CirclePlus, Delete, EditPen, Top, View } from "@element-plus/icons-vue";
import { API } from "@/api/modules/dwh/typings";
import { simpleUserTableDataController, userTableController } from "@/api/modules/dwh";
import { ColumnOptionsType, DialogType } from "@/utils/dict";
import { AxiosResponse } from "axios";
import { ElMessage } from "element-plus";
import { usePackDimension } from "@/hooks/usePackDimension";
import AddDataDialog from "@/views/dwh/tableColumn/addDataDialog.vue";
import { useHandleData } from "@/hooks/useHandleData";
import { getColumnOptionsType } from "@/utils/TableColumnUtil";
import { isArray } from "@/utils/is";

const router = useRouter();
const hideTableSelect = ref(true);

let route = useRoute();

const affixRoute = computed(() => {
  return route.params.id == ":id";
});
onMounted(() => {
  if (!affixRoute.value) {
    tableInfo.tableInfoId = isArray(route.params.id) ? route.params.id[0] : route.params.id;
  }
});

const toMenu = () => {
  router.push({
    name: "dwhMenu",
    query: {
      tableInfoId: tableInfo.tableInfoId,
      path: "/dwh/tableData",
      title: tableInfo.tableInfos.find((info: API.TableInfoVo) => info.id == tableInfo.tableInfoId)?.name ?? ""
    }
  });
};

const affixStyle = reactive({
  position: "absolute"
});

watch(hideTableSelect, (newVal, oldValue) => {
  if (newVal) {
    affixStyle.position = "absolute";
  } else {
    affixStyle.position = "static";
  }
});

const mouseleave = () => {
  if (document.querySelector(".tableInfoOptions")?.ariaHidden == "true") {
    hideTableSelect.value = true;
  }
};

// 表格配置项
const columns = ref<API.TableColumnVo[]>([]);

const { columnList, searchParam, aggColumn, validateRefs, primaryKeyCode } = usePackDimension(columns);

// ProTable 实例
const proTable = ref<ProTableInstance>();

// 如果表格需要初始化请求参数，直接定义传给 ProTable (之后每次请求都会自动带上该参数，此参数更改之后也会一直带上，改变此参数会自动刷新表格数据)
const initParam = reactive({ type: 1 });

// dataCallback 是对于返回的表格数据做处理，如果你后台返回的数据不是 list && total && pageNum && pageSize 这些字段，可以在这里进行处理成这些字段
// 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行
const dataCallback = (data: any) => {
  return {
    list: data.data,
    total: data.total ?? 0,
    pageNum: data.page ?? 1,
    pageSize: data.pageSize ?? 10
  };
};
const aggResult = reactive<{ [key: string]: any }>({});

// 如果你想在请求之前对当前请求参数做一些操作，可以自定义如下函数：params 为当前所有的请求参数（包括分页），最后返回请求列表接口
// 默认不做操作就直接在 ProTable 组件上绑定	:requestApi="getUserList"
const getTableList = async (params: any) => {
  if (!tableInfo.tableInfoId) {
    return {};
  }
  if (!columnList.value.find(column => column.isShow)?.isShow) {
    ElMessage.warning("您已隐藏了所有字段");
    return {};
  }
  let result = { data: {} };
  let query = { tableInfoId: Number(tableInfo.tableInfoId), whereParams: Object.values(searchParam) };
  let res: AxiosResponse<API.PageResultPageUserTableDataVo> = await simpleUserTableDataController.pageUserTableDataUsingPOST({
    page: pageConverter(params),
    query
  });
  let datas = res.data?.map(row => {
    let newData: { [key: string]: any } = {};
    row.tableData?.forEach(val => (newData[val.columnCode] = val.value));
    return newData;
  });
  result.data = { ...res };
  result.data.data = datas;

  let agg = await simpleUserTableDataController.queryAggregateUsingPOST(query);
  agg.data.forEach((item: API.UserTableDataVo) => {
    aggResult[item.columnCode] = item.value;
  });

  return result;
};

const tableInfo = reactive<{ tableInfoId: string; tableInfos: API.TableInfoVo[] }>({ tableInfoId: "", tableInfos: [] });

const loadTableInfos = async () => {
  let { data } = await userTableController.pageUserAuthTableUsingPOST({ page: { pageSize: 100, pageIndex: 1 } });
  tableInfo.tableInfos = data;
};

onMounted(async () => {
  loadTableInfos();
  if (!affixRoute.value) {
    tableInfo.tableInfoId = route.path.replace("/dwh/tableData/", "");
  }
});

const resetSearchParam = () => {
  Object.values(searchParam).forEach(param => (param.value = undefined));
};

const formatTableColumn = reactive<{ [key: string]: any }>({});
watch([() => tableInfo.tableInfoId], async newVal => {
  proTable.value?.clearTableData();
  let data = await userTableController.getUserAuthColumnUsingGET({ tableInfoId: Number(newVal[0]) });
  columns.value = data.data.authColumns;
  Object.assign(formatTableColumn, {});
  columns.value.forEach(column => {
    let columnOptionsType = getColumnOptionsType(column.columnOptions);
    if (columnOptionsType == ColumnOptionsType.custom) {
      formatTableColumn[column.columnCode] = column
        .columnOptions!.split(",")
        .reduce((accumulator: { [key: string]: any }, currentValue: string) => {
          // 设置初始值为空字符串或其他默认值
          let options = currentValue.split(":");
          accumulator[options[0]] = options[1];
          return accumulator;
        }, {});
    } else if (columnOptionsType == ColumnOptionsType.link_table) {
      let table = JSON.parse(column.columnOptions!);
      simpleUserTableDataController
        .pageUserTableDataUsingPOST({
          page: { pageIndex: 1, pageSize: 100 },
          query: { tableInfoId: Number(table.tableInfoId) }
        })
        .then(res => {
          formatTableColumn[column.columnCode] = res.data.reduce(
            (accumulator: { [key: string]: any }, item: API.PageUserTableDataVo) => {
              // 设置初始值为空字符串或其他默认值
              let valueCode = item.tableData?.find((tableData: API.UserTableDataVo) => tableData.columnCode == table.valueCode)
                ?.value;
              let valueLabel = item.tableData?.find((tableData: API.UserTableDataVo) => tableData.columnCode == table.valueLabel)
                ?.value;
              accumulator[valueCode] = valueLabel;
              return accumulator;
            },
            {}
          );
        });
    }
  });
});

const saveUserCustomizedColumnInfo = () => {
  userTableController.saveUserCustomizedColumnInfoUsingPOST({
    tableInfoId: Number(tableInfo.tableInfoId),
    columnInfo: columnList.value.map(({ prop, isShow }) => {
      return { columnCode: prop, show: isShow ? 1 : 0 };
    })
  });
};

const sortColumns = (newIndex: number, oldIndex: number) => {
  let splice = columns.value.splice(oldIndex, 1);
  columns.value.splice(newIndex, 0, splice[0]);
  saveUserCustomizedColumnInfo();
};

provide("saveUserCustomizedColumnInfo", saveUserCustomizedColumnInfo);
provide("sortColumns", sortColumns);

const reloadData = async () => {
  proTable.value?.getTableList();
};
// 添加数据
const addDataDialogRef = ref<InstanceType<typeof AddDataDialog> | null>(null);
const handlerTable = async (dialogType: DialogType, row?: { [key: string]: any }) => {
  if (dialogType === DialogType.delete) {
    let whereColumnValueParams = [];
    whereColumnValueParams.push({
      columnCode: primaryKeyCode.value,
      value: row[primaryKeyCode.value]
    });

    await useHandleData(
      simpleUserTableDataController.deleteUserTableDataUsingPOST,
      {
        tableInfoId: tableInfo.tableInfoId,
        whereColumnValueParams: whereColumnValueParams
      },
      "确定删除该记录"
    );
    reloadData();
    return;
  }
  addDataDialogRef.value?.show(row, dialogType === DialogType.show);
};
</script>
